/**
 * 映射类型
 */
namespace MapType {
    type OptionsFlags<Type> = {
        [Property in keyof Type]: Type[Property];
        // // [Property in keyof Type]: Type[keyof Type];
    };

    type Features = {
        darkMode: string;
        newUserProfile: number;
    };

    type FeatureOptions = OptionsFlags<Features>;


    // 在映射期间可以应用两个额外的修饰符：readonly 和 ? 分别影响可变性和可选性。
    type Person = {
        name: string;
        age: number;
    };

    // 给所有属性添加额外的修饰符
    type PersonFlags = {
        readonly [Property in keyof Person]: Person[Property];
        //  [Property in keyof Person]?: Person[Property];
    };
    type PersonOptions = PersonFlags;

    // 你可以通过添加前缀 - 或 + 来移除或添加这些已有或者未有修饰符。如果你不添加前缀，则假定为 +。

    type Animal = {
        readonly name?: string;
        readonly age?: number;
    };

    // 给所有属性添加额外的修饰符
    type AnimalFlags<T> = {
        //  -readonly [Property in keyof Animal]: Animal[Property];
        -readonly [Property in keyof T]-?: T[Property];
    };
    type AnimalOptions = AnimalFlags<Animal>;

    //  通过 as 重新映射键
//     为什么这里要用 string & Property，而不是直接 Property，并且为什么 string 可以这么用而别的类型不行？
//
// 🧠 解释一：防止 symbol 和 number 类型参与模板字面量拼接
//     模板字符串类型只能拼接 string 类型的键，不能拼接 symbol 类型的键（比如 Symbol.iterator），
//     而 keyof 的结果是可能包含：type K = keyof SomeType // => string | number | symbol

    // 所以模板字符串类型只能拼接 string 键，不能拼接 其它 键。 这里就要用到交叉类型约束

    type Getters<Type> = {
        [Property in keyof Type as `get${string & Property}`]: () => Type[Property];
    };
    type ar2 = number[]
    type sda = keyof ar2 //keyof string[] ⛳ 包含的是数组“实例”的键名，而不是静态的（Array 本身的方法）
    let datad3: sda = "length"


    interface Persons {
        name: string;
        age: number;
        location: string;
    }

    type LazyPerson = Getters<Persons>;
    let data22: LazyPerson = {
        getname() {
            return "adas"
        },
        getage() {
            return 1
        },
        getlocation() {
            return "adas"
        }
    }

    // 你可以通过条件类型生成 never 来过滤掉键：

    // Remove the 'kind' property
    type RemoveKindField<Type> = {
        [Property in keyof Type as Exclude<Property, "kind">]: Type[Property];
    };


    interface Circle {
        kind: "circle";
        radius: number;
    }

    type KindlessCircle = RemoveKindField<Circle>;
}
